#pragma once

#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <vector>

// uds client, 用于实现发送数据到管道对端, 采用临时文件描述符(sock), 对外接口: SendRequest, 自带有基准相关测试响应输出参数, 再外部堆栈可以使用基准公式进行计算
class UDSClient {
  public:
    explicit UDSClient(const std::string &socket_path) : sockfd_(-1), socket_path_(socket_path), duration_ns_(0), bytes_sent_(0), bytes_received_(0) {}

    ~UDSClient() {
        if (sockfd_ != -1) {
            close(sockfd_);
        }
    }

    // 原始字符串版本 (自动转换)
    bool SendRequest(const std::string &request, std::string &response) {
        std::vector<uint8_t> binary_response;
        if (!SendRequestImpl(request.data(), request.size(), binary_response)) {
            return false;
        }
        response.assign(binary_response.begin(), binary_response.end());
        return true;
    }

    // 二进制数据版本 (直接返回)
    bool SendRequest(const std::vector<uint8_t> &request, std::vector<uint8_t> &response) { return SendRequestImpl(request.data(), request.size(), response); }

    uint64_t GetLastDurationNs() const { return duration_ns_; }
    size_t GetLastBytesSent() const { return bytes_sent_; }
    size_t GetLastBytesReceived() const { return bytes_received_; }

  private:
    bool Connect() {
        sockfd_ = socket(AF_UNIX, SOCK_STREAM, 0);
        if (sockfd_ == -1) {
            std::cerr << "Failed to create socket: " << strerror(errno) << std::endl;
            return false;
        }

        struct sockaddr_un addr;
        memset(&addr, 0, sizeof(addr));
        addr.sun_family = AF_UNIX;
        strncpy(addr.sun_path, socket_path_.c_str(), sizeof(addr.sun_path) - 1);

        if (connect(sockfd_, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
            std::cerr << "Failed to connect to socket: " << strerror(errno) << std::endl;
            close(sockfd_);
            sockfd_ = -1;
            return false;
        }
        return true;
    }

    bool SendRequestImpl(const void *data, size_t size, std::vector<uint8_t> &response) {
        // 确保每次请求使用新连接
        if (sockfd_ != -1) {
            close(sockfd_);
            sockfd_ = -1;
        }

        if (!Connect()) {
            return false;
        }

        auto start = std::chrono::high_resolution_clock::now();
        response.clear();

        // 发送数据
        ssize_t sent_bytes = send(sockfd_, data, size, MSG_NOSIGNAL);
        if (sent_bytes == -1) {
            std::cerr << "Send failed: " << strerror(errno) << std::endl;
            return false;
        }

        // 半关闭写入端(只关闭write, 保持read通道)
        shutdown(sockfd_, SHUT_WR);

        // 接收响应 (recv返回0只表示连接已被对端正常关闭（对端调用了close()或也做了shutdown())
        uint8_t buffer[4096];
        ssize_t bytes_received;
        while ((bytes_received = recv(sockfd_, buffer, sizeof(buffer), 0)) > 0) {
            response.insert(response.end(), buffer, buffer + bytes_received);
        }

        auto end = std::chrono::high_resolution_clock::now();

        // 记录性能指标
        duration_ns_ = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
        bytes_sent_ = sent_bytes;
        bytes_received_ = response.size();

        return true;
    }

  private:
    int sockfd_;
    std::string socket_path_;
    uint64_t duration_ns_ = 0;
    size_t bytes_sent_ = 0;
    size_t bytes_received_ = 0;
};